---
title: PdfAPI.Core operations and processes
summary: Business and technical operations supported by this library.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-09-17
library: PdfAPI.Core
reference_type: package
---

# PdfAPI.Core operations and processes

This page is the operation catalog and cross-operation hub for this library. Each operation's detailed, step-by-step logic lives in its own page under `operations/`. The library exposes thirteen behaviour-bearing operations, all static members of `PdfAPI.Core.PdfClientService`, plus document lifecycle operations on `PdfAPI.Core.Document` and parsing operations on `PageRange`/`PdfTrackingMetadata`. No operation delegates into a referenced library other than iTextSharp and the BCL; none reads or writes a database, so no SQL IDs or tables apply to any step.

## Operation catalog
| Operation | Intent | Trigger | Inputs | Outputs | Rules | Tables | SQL |
| --- | --- | --- | --- | --- | --- | --- | --- |
| [Validate PDF bytes](operations/op-01-validate-pdf-bytes.md) | Guard that a byte array is a valid PDF before further processing | `ValidatePdf(byte[], string)` called | PDF bytes, optional file name | Passes silently, or throws `PdfException` | [BR-01](business-rules.md#br-01-pdf-signature-validation), [BR-02](business-rules.md#br-02-null-bytes-are-never-a-pdf), [BR-03](business-rules.md#br-03-invalid-pdf-input-aborts-with-pdfexception) | — | — |
| [Validate a document](operations/op-02-validate-a-document.md) | Guard that a `Document` loads and contains valid PDF bytes | `ValidatePdf(Document, PdfOptions)` called | `Document`, `PdfOptions` | Passes silently, source file possibly deleted, or throws `PdfException` | [BR-04](business-rules.md#br-04-document-validation-requires-a-non-null-document), [BR-05](business-rules.md#br-05-document-load-requires-in-memory-or-on-disk-bytes), [BR-06](business-rules.md#br-06-failed-document-load-aborts-validation), [BR-07](business-rules.md#br-07-input-file-cleanup-after-load) | — | — |
| [Test whether bytes are a PDF](operations/op-03-test-whether-bytes-are-a-pdf.md) | Report whether a byte array carries a PDF signature | `IsPdf(byte[])` called | PDF bytes | `true` / `false` | [BR-01](business-rules.md#br-01-pdf-signature-validation), [BR-02](business-rules.md#br-02-null-bytes-are-never-a-pdf) | — | — |
| [Read PDF version](operations/op-04-read-pdf-version.md) | Extract the PDF version token from the document header | `Version(byte[])` called | PDF bytes | Version string or `""` | [BR-01](business-rules.md#br-01-pdf-signature-validation), [BR-08](business-rules.md#br-08-pdf-version-extraction) | — | — |
| [Count pages](operations/op-05-count-pages.md) | Estimate the page count by scanning raw PDF markup | `GetPageCount(byte[])` called | PDF bytes | Integer page count | [BR-01](business-rules.md#br-01-pdf-signature-validation), [BR-09](business-rules.md#br-09-page-count-via-marker-scan) | — | — |
| [Detect form fields](operations/op-06-detect-form-fields.md) | Report whether a PDF carries fillable AcroForm fields | `HasFormFields(byte[])` called | PDF bytes | `true` / `false` | [BR-01](business-rules.md#br-01-pdf-signature-validation), [BR-10](business-rules.md#br-10-form-field-detection-requires-acroform) | — | — |
| [Flatten form fields](operations/op-07-flatten-form-fields.md) | Bake AcroForm field values into page content, removing interactivity | `Flatten(byte[])` called | PDF bytes | Flattened bytes, or original bytes unchanged | [BR-01](business-rules.md#br-01-pdf-signature-validation), [BR-11](business-rules.md#br-11-flattening-only-applies-with-acroform) | — | — |
| [Extract pages](operations/op-08-extract-pages.md) | Produce a new PDF containing only the selected page ranges | `ExtractPages(DocumentRange)` / `ExtractPageRanges(PdfReader, DocumentRange)` called | `DocumentRange` (Document + PageRange[]) | `PdfResult` wrapping a new `Document` | [BR-01](business-rules.md#br-01-pdf-signature-validation), [BR-12](business-rules.md#br-12-out-of-range-page-ranges-are-skipped), [BR-13](business-rules.md#br-13-page-boundaries-are-clamped-to-page-count), [BR-14](business-rules.md#br-14-original-range-copies-the-whole-document), [BR-15](business-rules.md#br-15-open-ended-stop-page-means-through-last-page), [BR-16](business-rules.md#br-16-descending-range-reverses-page-order), [BR-17](business-rules.md#br-17-successful-extraction-returns-a-new-succeeded-result), [BR-18](business-rules.md#br-18-extraction-result-records-processor-and-page-expression) | — | — |
| [Load a document](operations/op-09-load-a-document.md) | Materialise a `Document`'s bytes from memory or disk | `Document.Load(string, bool)` / `Document.Load(byte[], string)` / `Document.CreateEmpty(string)` called | File path, or bytes + extension | Loaded/created `Document`, or `false`/exception | [BR-05](business-rules.md#br-05-document-load-requires-in-memory-or-on-disk-bytes), [BR-19](business-rules.md#br-19-new-documents-receive-a-new-guid-identity), [BR-20](business-rules.md#br-20-missing-file-load-behavior), [BR-21](business-rules.md#br-21-document-file-name-convention) | — | — |
| [Persist and remove a document](operations/op-10-persist-and-remove-a-document.md) | Write a document to disk, or remove its backing file | `Document.Save(string)` / `Document.Delete()` / `Document.Dispose()` called | Destination directory, or none | File written, or file removed / `true`/`false` | [BR-22](business-rules.md#br-22-saving-a-document-writes-to-destination-directory), [BR-23](business-rules.md#br-23-document-deletion-never-throws), [BR-24](business-rules.md#br-24-disposing-a-document-deletes-its-file) | — | — |
| [Parse a page expression](operations/op-11-parse-a-page-expression.md) | Convert a page expression string into an array of `PageRange` | `PageRange.Parse(string)` called | Page expression (e.g., `"1-5,7,9-*,*"`) | Array of `PageRange` | [BR-25](business-rules.md#br-25-page-expression-token-grammar), [BR-26](business-rules.md#br-26-unmatched-tokens-are-skipped-silently), [BR-27](business-rules.md#br-27-absent-or-non-positive-stop-page-is-open-ended), [BR-28](business-rules.md#br-28-asterisk-means-all-pages), [BR-29](business-rules.md#br-29-bare-page-number-is-a-single-page-range), [BR-30](business-rules.md#br-30-empty-page-ranges-default-to-all-pages) | — | — |
| [Create tracking metadata](operations/op-12-create-tracking-metadata.md) | Compose a file-name tracking prefix encoding conversion and imaging intent | `PdfTrackingMetadata.Create(Guid, string, PdfConversionType, bool)` called | File id, application code, conversion type, imaging flag | Populated `PdfTrackingMetadata` with `FilePrefix` | [BR-31](business-rules.md#br-31-tracking-metadata-defaults), [BR-32](business-rules.md#br-32-tracking-prefix-conversion-type-character), [BR-33](business-rules.md#br-33-tracking-prefix-imaging-character), [BR-34](business-rules.md#br-34-tracking-prefix-format) | — | — |
| [Parse tracking metadata](operations/op-13-parse-tracking-metadata.md) | Decode a file-name tracking prefix back into structured metadata | `PdfTrackingMetadata.Parse(string)` called | Tracking prefix string | Populated `PdfTrackingMetadata`, or `null` | [BR-35](business-rules.md#br-35-tracking-prefix-parsing), [BR-36](business-rules.md#br-36-non-matching-prefix-yields-no-metadata), [BR-37](business-rules.md#br-37-tracking-metadata-parse-defect) | — | — |

## Process flow diagram
The following diagram visualizes the primary operational flow: guard, then inspect/transform/extract.

```mermaid
flowchart TD
	Start([Caller invokes PdfClientService]) --> Guard["IsPdf / ValidatePdf<br>(BR-01, BR-02, BR-03)"]
	Guard -->|Invalid| Fail([Throws PdfException])
	Guard -->|Valid| Kind{"Which operation?"}
	Kind -->|Inspect| Inspect["Version / GetPageCount /<br>HasFormFields"]
	Kind -->|Transform| Transform["Flatten"]
	Kind -->|Extract| Extract["ExtractPages /<br>ExtractPageRanges"]
	Inspect --> Done([Return value])
	Transform --> Done
	Extract --> Result(["PdfResult: Succeeded"])
```

## Failure and edge-case behavior
- A null or non-PDF byte array causes `ValidatePdf` to throw `PdfException` ([BR-03](business-rules.md#br-03-invalid-pdf-input-aborts-with-pdfexception)); other inspection operations (`IsPdf`) return `false` rather than throwing.
- `ValidatePdf(Document, PdfOptions)` deletes the input file before checking the PDF signature, so a document that fails validation has already lost its on-disk copy ([BR-07](business-rules.md#br-07-input-file-cleanup-after-load)).
- A page range wholly beyond the document end is silently skipped rather than raising an error ([BR-12](business-rules.md#br-12-out-of-range-page-ranges-are-skipped)); a page-expression token that does not match the grammar is silently dropped ([BR-26](business-rules.md#br-26-unmatched-tokens-are-skipped-silently)).
- `Document.Delete()` swallows all exceptions and reports `false` rather than propagating a failure ([BR-23](business-rules.md#br-23-document-deletion-never-throws)).
- `PdfTrackingMetadata.Parse` always returns `ShouldBeImaged = false` and `ConversionType = Convert`, regardless of the encoded prefix, due to a capture-group name mismatch ([BR-37](business-rules.md#br-37-tracking-metadata-parse-defect)).

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Architecture](architecture.md)
- [Dependencies](dependencies.md)
- [Business rules](business-rules.md)
- [Security and authorization](security-authorization.md)
- [API reference](api/index.md)

## Sources
- `PdfAPI.Core\Services\PdfClientService.cs`
- `PdfAPI.Core\Document.cs`
- `PdfAPI.Core\Extract\DocumentRange.cs`
- `PdfAPI.Core\Extract\PageRange.cs`
- `PdfAPI.Core\PdfTrackingMetadata.cs`
